*/
#include "defs.h"
-#if !NO_EXPAT
-#include <expat.h>
-static XML_Parser psr;
-#endif
+#include "xmlgeneric.h"
-static int in_wpt;
-static int in_name;
-static int in_link;
-static int in_type;
-static int in_cdata;
-static char *cdatastr;
-static char *typestr;
static char *deficon = NULL;
static waypoint *wpt_tmp;
{
}
#else
-static void
-tag_coord(const char **attrv)
-{
- const char **avp = &attrv[0];
-
-
- while (*avp) {
- if (strcmp(avp[0], "lat") == 0) {
- sscanf(avp[1], "%lf",
- &wpt_tmp->latitude);
- }
- else if (strcmp(avp[0], "lon") == 0) {
- sscanf(avp[1], "%lf",
- &wpt_tmp->longitude);
- }
- avp+=2;
- }
+
+static xg_callback wpt_s, wpt_e;
+static xg_callback wpt_link_s, wpt_link;
+static xg_callback wpt_name, wpt_name_s, wpt_type, wpt_coord;
+
+static
+xg_tag_mapping loc_map[] = {
+ { wpt_s, cb_start, "/loc/waypoint" },
+ { wpt_e, cb_end, "/loc/waypoint" },
+ { wpt_name_s, cb_start, "/loc/waypoint/name" },
+ { wpt_name, cb_cdata, "/loc/waypoint/name" },
+ { wpt_type, cb_cdata, "/loc/waypoint/type" },
+ { wpt_link_s, cb_start, "/loc/waypoint/link" },
+ { wpt_link, cb_cdata, "/loc/waypoint/link" },
+ { wpt_coord, cb_start, "/loc/waypoint/coord" },
+ { NULL, 0, NULL }
+};
+
+void wpt_s(const char *args, const char **unused)
+{
+// wpt_tmp = waypt_new();
+ wpt_tmp = xcalloc(sizeof(*wpt_tmp), 1);
}
-static void
-tag_name(const char **attrv)
+void wpt_e(const char *args, const char **unused)
{
- const char **avp = &attrv[0];
- while (*avp) {
- if (strcmp(avp[0], "id") == 0) {
- wpt_tmp->shortname = xstrdup(avp[1]);
- }
- avp+=2;
- }
+ waypt_add(wpt_tmp);
}
-static void
-tag_type(const char **attrv)
+void wpt_name_s(const char *args, const char **attrv)
{
- const char **avp = &attrv[0];
- while (*avp) {
- if (strcmp(avp[0], "type") == 0) {
- wpt_tmp->icon_descr = xstrdup(avp[1]);
- }
- avp+=2;
- }
+ const char **avp = &attrv[0];
+ while (*avp) {
+ if (0 == strcmp(avp[0], "id")) {
+ wpt_tmp->shortname = xstrdup(avp[1]);
+ }
+ avp+=2;
+ }
}
-static void
-tag_link(const char **attrv)
+void wpt_name(const char *args, const char **unused)
{
- const char **avp = &attrv[0];
- while (*avp) {
- if (strcmp(avp[0], "text") == 0) {
- wpt_tmp->url_link_text = xstrdup(avp[1]);
- }
- avp+=2;
- }
+ if (args) wpt_tmp->description = xstrdup(args);
}
-static void
-geo_start(void *data, const char *el, const char **attr)
+void wpt_link_s(const char *args, const char **attrv)
{
-
- if (in_wpt) {
- if (strcmp(el, "ele") == 0) {
- wpt_tmp->altitude = atoi(attr[1]);
- }
- else if (strcmp(el, "name") == 0) {
- tag_name(attr);
- }
- else if (strcmp(el, "coord") == 0) {
- tag_coord(attr);
- }
- else if (strcmp(el, "type") == 0) {
- tag_type(attr);
- }
- }
-
- if (strcmp(el, "waypoint") == 0) {
- wpt_tmp = xcalloc(sizeof(*wpt_tmp), 1);
- in_wpt++;
- } else if (strcmp(el, "name") == 0) {
- in_name++;
- } else if (strcmp(el, "type") == 0) {
- tag_type(attr);
- in_type++;
- } else if (strcmp(el, "link") == 0) {
- tag_link(attr);
- in_link++;
- }
+ const char **avp = &attrv[0];
+ while (*avp) {
+ if (0 == strcmp(avp[0], "text")) {
+ wpt_tmp->url_link_text = xstrdup(avp[1]);
+ }
+ avp+=2;
+ }
+}
+void wpt_link(const char *args, const char **attrv)
+{
+ wpt_tmp->url = xstrdup(args);
}
-static void
-geo_end(void *data, const char *el)
+void wpt_type(const char *args, const char **unused)
{
- if (in_cdata) {
- if (in_name) {
- wpt_tmp->description = xstrdup(cdatastr);
- }
- if (in_link) {
- wpt_tmp->url = xstrdup(cdatastr);
- }
- in_cdata--;
- memset(cdatastr,0, MY_CBUF);
- }
- if (strcmp(el, "waypoint") == 0) {
- waypt_add(wpt_tmp);
- in_wpt--;
- }
- else if (strcmp(el, "name") == 0) {
- in_name--;
- }
- else if (strcmp(el, "type") == 0) {
- wpt_tmp->icon_descr_is_dynamic = 1;
- wpt_tmp->icon_descr = xstrdup(typestr);
- memset(typestr,0, MY_CBUF);
- in_type--;
- }
- else if (strcmp(el, "link") == 0) {
- in_link--;
- }
+ wpt_tmp->icon_descr_is_dynamic = 1;
+ wpt_tmp->icon_descr = xstrdup(args);
}
-static void
-geo_cdata(void *dta, const XML_Char *s, int len)
+void wpt_coord(const char *args, const char **attrv)
{
- char *estr;
- if (in_name || in_link) {
- estr = cdatastr + strlen(cdatastr);
- memcpy(estr, s, len);
- in_cdata++;
- }
- if (in_type) {
- estr = typestr + strlen(typestr);
- memcpy(estr, s, len);
- }
+ const char **avp = &attrv[0];
+
+ while (*avp) {
+ if (strcmp(avp[0], "lat") == 0) {
+ sscanf(avp[1], "%lf",
+ &wpt_tmp->latitude);
+ }
+ else if (strcmp(avp[0], "lon") == 0) {
+ sscanf(avp[1], "%lf",
+ &wpt_tmp->longitude);
+ }
+ avp+=2;
+ }
}
void
geo_rd_init(const char *fname)
{
- fd = xfopen(fname, "r", MYNAME);
-
- psr = XML_ParserCreate(NULL);
- if (!psr) {
- fatal(MYNAME ":Cannot create XML parser\n");
- }
-
- XML_SetElementHandler(psr, geo_start, geo_end);
- cdatastr = xcalloc(MY_CBUF,1);
- typestr = xcalloc(MY_CBUF,1);
- XML_SetCharacterDataHandler(psr, geo_cdata);
+ xml_init(fname, loc_map);
}
void
geo_read(void)
{
- int len;
- char buf[MY_CBUF];
-
- while ((len = fread(buf, 1, sizeof(buf), fd))) {
- if (!XML_Parse(psr, buf, len, feof(fd))) {
- fatal(MYNAME ":Parse error at %d: %s\n",
- XML_GetCurrentLineNumber(psr),
- XML_ErrorString(XML_GetErrorCode(psr)));
- }
- }
-
- XML_ParserFree(psr);
+ xml_read();
}
-
#endif
void
geo_rd_deinit(void)
{
- if ( cdatastr ) {
- xfree(cdatastr);
- }
- if ( typestr ) {
- xfree(typestr);
- }
- fclose(fd);
+ xml_deinit();
}
void
--- /dev/null
+/*
+ Common utilities for XML-based formats.
+
+ Copyright (C) 2004 Robert Lipe, robertlipe@usa.net
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA
+
+ */
+
+#include "defs.h"
+#include "xmlgeneric.h"
+
+#ifndef NO_EXPAT
+ #include <expat.h>
+ static XML_Parser psr;
+#endif
+
+static vmem_t current_tag;
+static vmem_t cdatastr;
+static FILE *ifd;
+static xg_tag_mapping *xg_tag_tbl;
+
+#define MY_CBUF 4096
+
+#define MYNAME "XML Reader"
+
+void
+write_xml_entity(FILE *ofd, const char *indent,
+ const char *tag, const char *value)
+{
+ char *tmp_ent = xml_entitize(value);
+ fprintf(ofd, "%s<%s>%s</%s>\n", indent, tag, tmp_ent, tag);
+ xfree(tmp_ent);
+}
+
+void
+write_optional_xml_entity(FILE *ofd, const char *indent,
+ const char *tag, const char *value)
+{
+ if (value && *value)
+ write_xml_entity(ofd, indent, tag, value);
+}
+
+
+/***********************************************************************
+ * These implement a simple interface for "generic" XML that
+ * maps reasonably close to 1:1 between XML tags and internal data
+ * structures.
+ *
+ * It doesn't work well for formats (like GPX) that really are "real"
+ * XML with extended namespaces and such, but it handles many simpler
+ * xml strains and insulates us from a lot of the grubbiness of expat.
+ */
+
+xg_callback *
+xml_tbl_lookup(const char *tag, xg_cb_type cb_type)
+{
+ xg_tag_mapping *tm;
+ for (tm = xg_tag_tbl; tm->tag_cb != NULL; tm++) {
+ if (0 == strcmp(tm->tag_name, tag) && (cb_type == tm->cb_type)) {
+ return tm->tag_cb;
+ }
+ }
+ return NULL;
+}
+
+
+static void
+xml_start(void *data, const char *el, const char **attr)
+{
+ char *e;
+ char *ep;
+ xg_callback *cb;
+
+ vmem_realloc(¤t_tag, strlen(current_tag.mem) + 2 + strlen(el));
+
+ e = current_tag.mem;
+ ep = e + strlen(e);
+ *ep++ = '/';
+ strcpy(ep, el);
+
+ memset(cdatastr.mem, 0, cdatastr.size);
+
+ cb = xml_tbl_lookup(e, cb_start);
+ if (cb) {
+ (*cb)(NULL, attr);
+ }
+}
+
+static void
+xml_cdata(void *dta, const XML_Char *s, int len)
+{
+ char *estr;
+ xg_callback *cb;
+
+ vmem_realloc(&cdatastr, 1 + len + strlen(cdatastr.mem));
+ estr = (char *) cdatastr.mem + strlen(cdatastr.mem);
+ memcpy(estr, s, len);
+ estr[len] = 0;
+
+ cb = xml_tbl_lookup(current_tag.mem, cb_cdata);
+ if (cb) {
+ (*cb)(estr, NULL);
+ }
+}
+
+static void
+xml_end(void *data, const char *el)
+{
+ char *s = strrchr(current_tag.mem, '/');
+ xg_callback *cb;
+
+ if (strcmp(s + 1, el)) {
+ fprintf(stderr, "Mismatched tag %s\n", el);
+ }
+
+ cb = xml_tbl_lookup(current_tag.mem, cb_end);
+ if (cb) {
+ (*cb)(el, NULL);
+ }
+ *s = 0;
+}
+
+void xml_read(void)
+{
+ int len;
+ char buf[MY_CBUF];
+
+ while ((len = fread(buf, 1, sizeof(buf), ifd))) {
+ if (!XML_Parse(psr, buf, len, feof(ifd))) {
+ fatal(MYNAME ":Parse error at %d: %s\n",
+ XML_GetCurrentLineNumber(psr),
+ XML_ErrorString(XML_GetErrorCode(psr)));
+ }
+ }
+ XML_ParserFree(psr);
+
+}
+
+void
+xml_init(const char *fname, xg_tag_mapping *tbl)
+{
+ ifd = xfopen(fname, "r", MYNAME);
+
+ current_tag = vmem_alloc(1,0);
+ *((char *)current_tag.mem) = '\0';
+
+ psr = XML_ParserCreate(NULL);
+ if (!psr) {
+ fatal(MYNAME ": Cannot create XML Parser\n");
+ }
+
+ cdatastr = vmem_alloc(1, 0);
+ *((char *)cdatastr.mem) = '\0';
+
+ xg_tag_tbl = tbl;
+
+ XML_SetElementHandler(psr, xml_start, xml_end);
+ XML_SetCharacterDataHandler(psr, xml_cdata);
+}
+
+void
+xml_deinit(void)
+{
+ vmem_free(¤t_tag);
+ vmem_free(&cdatastr);
+}
+
+/******************************************/
--- /dev/null
+/*
+ Header for our common utilities for XML-based formats.
+
+ Copyright (C) 2004 Robert Lipe, robertlipe@usa.net
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA
+
+ */
+
+
+
+typedef enum {
+ cb_start = 1,
+ cb_cdata,
+ cb_end,
+} xg_cb_type;
+
+typedef void (xg_callback) (const char *, const char **);
+
+typedef struct xg_tag_mapping {
+ xg_callback *tag_cb;
+ xg_cb_type cb_type;
+ const char *tag_name;
+} xg_tag_mapping;
+
+
+void write_xml_entity(FILE *ofd, const char *indent,
+ const char *tag, const char *value);
+
+void write_optional_xml_entity(FILE *ofd, const char *indent,
+ const char *tag, const char *value);
+
+void xml_init(const char *fname, xg_tag_mapping *tbl);
+void xml_read(void);
+void xml_deinit(void);